import {
  ElButton,
  ElCheckbox,
  ElCheckboxGroup,
  ElForm,
  ElFormItem,
  ElInput,
  ElRadio,
  ElRadioGroup,
  ElRadioButton,
  ElSelect,
  ElCard,
  ElRow,
  ElCol,
  ElTabs,
  ElTabPane,
  ElDatePicker,
  ElDialog,
  ElUpload,
  ElProgress,
  ElDropdown,
  ElDropdownItem,
  ElDropdownMenu,
  ElPopover,
  ElTable,
  ElTableColumn,
  ElLoading, ElSelectV2, ElAlert, ElLink
} from 'element-plus'
import { App, computed, inject, InjectionKey, provide, reactive, ref } from 'vue'
import _ from 'lodash'

export default (app: App): void => {
  app.config.globalProperties.$ELEMENT = {
    size: 'small'
  }

  app.use(ElButton)
    .use(ElInput)
    .use(ElForm)
    .use(ElFormItem)
    .use(ElCheckbox)
    .use(ElCheckboxGroup)
    .use(ElRadio)
    .use(ElRadioGroup)
    .use(ElRadioButton)
    .use(ElSelect)
    .use(ElCard)
    .use(ElRow)
    .use(ElCol)
    .use(ElTabs)
    .use(ElTabPane)
    .use(ElDatePicker)
    .use(ElDialog)
    .use(ElUpload)
    .use(ElProgress)
    .use(ElDropdown)
    .use(ElDropdownItem)
    .use(ElDropdownMenu)
    .use(ElPopover)
    .use(ElTable)
    .use(ElTableColumn)
    .use(ElLoading)
    .use(ElSelectV2)
    .use(ElAlert)
    .use(ElLink)
}

export const createForm = (): ElFormRoot => {
  return ref() as any
}

export const createStateKey = <T>(): InjectionKey<ElFormType<T>> => Symbol()

export const provideDialogState = <T>(
  key: InjectionKey<ElFormType<T>>,
  defaultValues: T,
  success: ElFormSuccess
) => {
  const dialog = reactive<ElFormType<T>>({
    visible: false,
    title: '',
    formData: _.clone(defaultValues),
    show: (title: string, data?: any) => {
      dialog.title = title
      if (data) {
        dialog.formData = _.clone({ ...defaultValues, ...data })
      }
      dialog.visible = true
    },
    hide: () => {
      // dialog.formData = {} as any
      dialog.visible = false
    },
    success
  })
  provide(key, dialog as any)
  return dialog
}

export const injectDialogState = <T>(key: InjectionKey<ElFormType<T>>) => {
  const dialog = inject(key)
  return {
    visible: computed({
      get: () => dialog?.visible,
      set: (v) => {
        if (v) {
          dialog?.show(`${dialog?.title}`, dialog?.formData)
        } else {
          dialog?.hide()
        }
      }
    }),
    title: computed(() => dialog?.title),
    formData: computed(() => dialog?.formData),
    show: (title: string, data?: any) => dialog?.show(title, data),
    hide: () => dialog?.hide(),
    success: dialog?.success
  }
}
